/**
 * 
 */
package de.cbf.cam.dsa.tavern.carte.ui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Text;

import de.cbf.cam.dsa.tavern.carte.exceptions.WrongTypeProvidedException;
import de.cbf.cam.dsa.tavern.carte.model.entities.Ingredient;
import de.cbf.cam.dsa.tavern.carte.model.entities.Processing;
import de.cbf.cam.dsa.tavern.carte.model.entities.interfaces.IEditableEntity;
import de.cbf.cam.dsa.tavern.carte.ui.listeners.EnterPositiveDoubleForEvent;

/**
 * @author Stefan Alter
 *
 */
public class CompositeEditProcessingData extends Composite {
	private Composite					compositeValues 			= null;
	private Composite					compositeAddendumCategories = null;
	private CompositeIngredients		compositeIngredients 		= null;	
	//
	private Label staticName			= null;
	private Label staticPrice			= null;
	private Label staticAddendums		= null;	
	private Text textName				= null;	
	private Text textPrice				= null;
	private List listAddendums			= null;
	//	
	private Button buttonToAddendums	= null;
	private Button buttonFromAddendums	= null;
	
	/**
	 * @param parent
	 * @param style
	 */
	public CompositeEditProcessingData(Composite parent, int style) {
		super(parent, style);
		initialize();		
	}

	/**
	 * This method initializes this
	 * 
	 */
	private void initialize() {
        GridLayout layout = new GridLayout();
	        layout.numColumns			= 2;	        
	        layout.horizontalSpacing	= 2;
	        layout.verticalSpacing		= 3;
	        layout.marginWidth			= 0;
	        layout.marginHeight 		= 0;
	        layout.marginTop			= 2;
	    //
        this.setLayout(layout);        
        //
        createCompositeValues();        
        createCompositeIngredients();
        createCompositeAddendumCategories();      
		//
        registerListeners();
        registerAdvancementListeners();
        //
        init();
	}
	private void registerListeners() {
		buttonToAddendums.addSelectionListener(addToAddendums);
		buttonFromAddendums.addSelectionListener(removeFromAddendums);		
		//
		textName.addModifyListener(nameModify);		
		EnterPositiveDoubleForEvent.addToText(textPrice, priceModifyListeners);
		//
		listAddendums.addSelectionListener(categorySelection);
	}

	private void registerAdvancementListeners(){
		compositeIngredients.registerSelectionListener(ingredientSelection);
	}
	private void init() {
		
		buttonFromAddendums.setEnabled(false);
		buttonToAddendums.setEnabled(false);		
	}

	/**
	 * This method initializes compositeValues	
	 */
	private void createCompositeValues() {
		GridLayout layoutCompositeValues = new GridLayout();
			layoutCompositeValues.numColumns		= 2;		
			layoutCompositeValues.marginWidth		= 0;
			layoutCompositeValues.marginHeight		= 0;
			layoutCompositeValues.horizontalSpacing	= 5;
			layoutCompositeValues.verticalSpacing	= 2;
		GridData gDCompositeValues = new GridData();
			gDCompositeValues.horizontalAlignment		= GridData.FILL;
			gDCompositeValues.verticalAlignment			= GridData.CENTER;
			gDCompositeValues.grabExcessHorizontalSpace	= false;
			gDCompositeValues.grabExcessVerticalSpace	= false;			
		GridData gDTextName = new GridData();
			gDTextName.horizontalAlignment			= GridData.FILL;
			gDTextName.verticalAlignment			= GridData.CENTER;
			gDTextName.grabExcessHorizontalSpace	= true;
		GridData gDTextPrice = new GridData();
			gDTextPrice.horizontalAlignment			= GridData.FILL;
			gDTextPrice.verticalAlignment			= GridData.CENTER;
			gDTextPrice.grabExcessHorizontalSpace	= true;		
		//
		compositeValues = new Composite(this, SWT.NONE);
		compositeValues.setLayout(layoutCompositeValues);
		compositeValues.setLayoutData(gDCompositeValues);	
		//
		staticName = new Label(compositeValues, SWT.NONE);
		staticName.setText("Name:");
		//
		textName = new Text(compositeValues, SWT.BORDER);
		textName.setLayoutData(gDTextName);
		//
		staticPrice = new Label(compositeValues, SWT.NONE);
		staticPrice.setText("Preis:");
		//
		textPrice = new Text(compositeValues, SWT.BORDER | SWT.RIGHT);
		textPrice.setLayoutData(gDTextPrice);
	}

	/**
	 * This method initializes compositeAddendumCategories	
	 *
	 */
	private void createCompositeAddendumCategories() {
		GridLayout layoutCompositeAddendumCategories = new GridLayout();
			layoutCompositeAddendumCategories.numColumns			= 2;			
			layoutCompositeAddendumCategories.marginWidth			= 0;
			layoutCompositeAddendumCategories.marginHeight			= 0;
			layoutCompositeAddendumCategories.horizontalSpacing		= 0;
			layoutCompositeAddendumCategories.verticalSpacing		= 0;
		GridData gDCompositeAddendumCategories = new GridData();			
			gDCompositeAddendumCategories.horizontalAlignment		= GridData.FILL;
			gDCompositeAddendumCategories.verticalAlignment			= GridData.FILL;
			gDCompositeAddendumCategories.grabExcessHorizontalSpace	= false;
			gDCompositeAddendumCategories.grabExcessVerticalSpace	= true;
		GridData gDStaticAddendums = new GridData();
			gDStaticAddendums.horizontalSpan 						= 2;
		GridData gDBtnFromAddendums = new GridData();			
			gDBtnFromAddendums.verticalAlignment = GridData.BEGINNING;
			gDBtnFromAddendums.horizontalAlignment = GridData.FILL;
			gDBtnFromAddendums.grabExcessVerticalSpace				= true;
		GridData gDBtnToAddendums = new GridData();
			gDBtnToAddendums.verticalAlignment						= GridData.END;
			gDBtnToAddendums.horizontalAlignment					= GridData.CENTER;
			gDBtnToAddendums.grabExcessVerticalSpace				= true;		
		GridData gDListAddendums = new GridData();
			gDListAddendums.horizontalAlignment						= GridData.FILL;
			gDListAddendums.verticalAlignment						= GridData.FILL;			
			gDListAddendums.grabExcessHorizontalSpace				= true;
			gDListAddendums.grabExcessVerticalSpace					= true;
			gDListAddendums.verticalSpan							= 2;
			gDListAddendums.widthHint								= 100;
		//
		compositeAddendumCategories = new Composite(this, SWT.NONE);
		compositeAddendumCategories.setLayoutData(gDCompositeAddendumCategories);
		compositeAddendumCategories.setLayout(layoutCompositeAddendumCategories);
		
		staticAddendums = new Label(compositeAddendumCategories,SWT.NONE);
		staticAddendums.setText("Addendums:");
		staticAddendums.setLayoutData(gDStaticAddendums);
		
		listAddendums = new List(compositeAddendumCategories, SWT.BORDER);
		listAddendums.setLayoutData(gDListAddendums);
		
		buttonToAddendums = new Button(compositeAddendumCategories, SWT.NONE);
		buttonToAddendums.setText("<<");
		buttonToAddendums.setLayoutData(gDBtnToAddendums);
		
		buttonFromAddendums = new Button(compositeAddendumCategories, SWT.NONE);
		buttonFromAddendums.setText("XX");
		buttonFromAddendums.setLayoutData(gDBtnFromAddendums);
	}

	/**
	 * This method initializes compositeIngredients	
	 *
	 */
	private void createCompositeIngredients() {		
		GridData gDCompositeEntitiesIngredients = new GridData();
			gDCompositeEntitiesIngredients.horizontalAlignment			= GridData.FILL;
			gDCompositeEntitiesIngredients.verticalAlignment			= GridData.FILL;
			gDCompositeEntitiesIngredients.grabExcessHorizontalSpace	= true;
			gDCompositeEntitiesIngredients.grabExcessVerticalSpace		= true;		
			gDCompositeEntitiesIngredients.verticalSpan					= 2;
		//
		compositeIngredients = new CompositeIngredients(this, SWT.NONE);
		
		compositeIngredients.setLayoutData(gDCompositeEntitiesIngredients);
	}

	public void clearData() {
		textName.setText("");
		textPrice.setText("");
		listAddendums.removeAll();		
	}
	
	@Override
	public void setEnabled(boolean enabled) {
		textName.setEnabled(enabled);
		textPrice.setEnabled(enabled);
		listAddendums.setEnabled(enabled);		
		compositeIngredients.setEnabled(enabled);
		if( ! enabled){			//buttons are only switched off
			buttonFromAddendums.setEnabled(enabled);
			buttonToAddendums.setEnabled(enabled);			
		}	
	}	

	public String getProcessingName(){
		return textName.getText();
	}
	public Double getPrice(){
		String text = textPrice.getText();
		if(text.equals("")){
			return 0D;
		}
		return Double.parseDouble(text);
	}	
	public Ingredient getSelectedIngredient(){
		return compositeIngredients.getSelectedObject();
	}
	public String getSelectedAddendumCategory(){
		int index = listAddendums.getSelectionIndex();
		if(index >= 0){
			return listAddendums.getItem(index);
		}else{
			return null;
		}		
	}
	
	public void setButtonFromAddendumsEnabled(boolean value) {
		buttonFromAddendums.setEnabled(value);
	}
	public void setButtonToAddendumsEnabled(boolean value) {
		buttonToAddendums.setEnabled(value);
	}
	/* (non-Javadoc)
	 * @see de.cbf.cam.dsa.tavern.carte.ui.interfaces.ICompositeEditEntity#setEntity(de.cbf.cam.dsa.tavern.carte.model.entities.interfaces.IEditableEntity)
	 */	
	public void setEntityData(IEditableEntity value)
			throws IllegalArgumentException {		
		if (value instanceof Processing) {
			Processing processing = (Processing) value;
			Point selection = textName.getSelection();
			textName.setText(processing.getName());
			textName.setSelection(selection);
			selection = textPrice.getSelection();
			textPrice.setText(processing.getModifiedPrice().toString());
			textPrice.setSelection(selection);
			Iterator<String> iterator = processing.iteratorPossibleAddendumCategories();			
			int index = listAddendums.getSelectionIndex();
			listAddendums.removeAll();
			while (iterator.hasNext()) {
				String category = (String) iterator.next();			
				listAddendums.add(category);
			}
			if(index >= 0){
				listAddendums.select(index);
				listAddendums.notifyListeners(SWT.Selection, new Event());//notify of new selection
			}			
		}else{
			if(value == null)return;
			throw new WrongTypeProvidedException(Processing.class,value.getClass());	
		}
	}
	
	public void setIngredients(Iterator<Ingredient> iteratorIngredients) {
		compositeIngredients.setObjects(Ingredient.transformIngredientIterator(iteratorIngredients).iterator());		
	}
	
	private Collection<ActionListener> nameModifyListeners = new ArrayList<ActionListener>();
	public boolean registerNameModifyListener(ActionListener listener){
		return nameModifyListeners.add(listener);
	}
	public boolean deRegisterNameModifyListener(ActionListener listener){
		return nameModifyListeners.remove(listener);
	}
	private NameModifyAdvancer nameModify = new NameModifyAdvancer();  //  @jve:decl-index=0:
	private class NameModifyAdvancer implements ModifyListener{
		@Override
		public void modifyText(ModifyEvent e) {
			ActionEvent event = new ActionEvent(CompositeEditProcessingData.this, ActionEvent.ACTION_PERFORMED, "NameModify");
			for (ActionListener listener : nameModifyListeners) {
				listener.actionPerformed(event);
			}			
		}			
	}
	private Collection<ActionListener> priceModifyListeners = new ArrayList<ActionListener>();
	public boolean registerPriceModifyListener(ActionListener listener){
		return priceModifyListeners.add(listener);
	}
	public boolean deRegisterPriceModifyListener(ActionListener listener){
		return priceModifyListeners.remove(listener);
	}
	//see register listeners for "missing" Price modify listener, it is
	//incorporated in EnterPositiveDoubleForEvent
	
	private Collection<ActionListener> addToAddendumsListeners = new ArrayList<ActionListener>();
	public boolean registerAddToAddendumsListener(ActionListener listener){
		return addToAddendumsListeners.add(listener);
	}
	public boolean deRegisterAddToAddendumsListener(ActionListener listener){
		return addToAddendumsListeners.remove(listener);
	}
	private AddToAddendumsAdvancer addToAddendums = new AddToAddendumsAdvancer();
	private class AddToAddendumsAdvancer extends SelectionAdapter{
		@Override
		public void widgetSelected(SelectionEvent e) {
			ActionEvent event = new ActionEvent(CompositeEditProcessingData.this, ActionEvent.ACTION_PERFORMED, "AddToAddendums");
			for (ActionListener listener : addToAddendumsListeners) {
				listener.actionPerformed(event);
			}
		}		
	}
	private Collection<ActionListener> removeFromAddendumsListeners = new ArrayList<ActionListener>();
	public boolean registerRemoveFromAddendumsListener(ActionListener listener){
		return removeFromAddendumsListeners.add(listener);
	}
	public boolean deRegisterRemoveFromAddendumsListener(ActionListener listener){
		return removeFromAddendumsListeners.remove(listener);
	}
	private RemoveFromAddendumsAdvancer removeFromAddendums = new RemoveFromAddendumsAdvancer();
	private class RemoveFromAddendumsAdvancer extends SelectionAdapter{
		@Override
		public void widgetSelected(SelectionEvent e) {
			ActionEvent event = new ActionEvent(CompositeEditProcessingData.this, ActionEvent.ACTION_PERFORMED, "RemoveFromAddendums");
			for (ActionListener listener : removeFromAddendumsListeners) {
				listener.actionPerformed(event);
			}
		}		
	}
	
	private Collection<ActionListener> ingredientSelectionListeners = new ArrayList<ActionListener>();
	public boolean registerIngredientSelectionListener(ActionListener listener){
		return ingredientSelectionListeners.add(listener);
	}
	public boolean deRegisterIngredientSelectionListener(ActionListener listener){
		return ingredientSelectionListeners.remove(listener);
	}
	private IngredientSelectionAdvancer ingredientSelection = new IngredientSelectionAdvancer();	
	private class IngredientSelectionAdvancer implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			ActionEvent event = new ActionEvent(CompositeEditProcessingData.this, ActionEvent.ACTION_PERFORMED, "IngredientSelection:"+e.getActionCommand());
			for (ActionListener listener : ingredientSelectionListeners) {
				listener.actionPerformed(event);
			}
		}		
	}
	
	private Collection<ActionListener> categorySelectionListeners = new ArrayList<ActionListener>();  //  @jve:decl-index=0:
	public boolean registerCategorySelectionListener(ActionListener listener){
		return categorySelectionListeners.add(listener);
	}
	public boolean deRegisterCategorySelectionListener(ActionListener listener){
		return categorySelectionListeners.remove(listener);
	}
	private CategorySelectionAdvancer categorySelection = new CategorySelectionAdvancer();
	private class CategorySelectionAdvancer extends SelectionAdapter{
		@Override
		public void widgetSelected(SelectionEvent e) {
			ActionEvent event = new ActionEvent(CompositeEditProcessingData.this, ActionEvent.ACTION_PERFORMED, "CategorySelection");
			for (ActionListener listener : categorySelectionListeners) {
				listener.actionPerformed(event);
			}
		}		
	}
	
	
	

}  //  @jve:decl-index=0:visual-constraint="10,10"
